package com.irdstudio.apicenter.gateway.web.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;

import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.irdstudio.apicenter.gateway.comm.MaccsPacket;
import com.irdstudio.apicenter.gateway.comm.MaccsPacketUtil;
import com.irdstudio.apicenter.gateway.core.jdbc.MaccsBaseDAO;
import com.irdstudio.apicenter.gateway.util.PathUtil;
import com.irdstudio.apicenter.gateway.util.spring.BeanUtils;
import com.irdstudio.apicenter.gateway.web.MaccsException;
import com.irdstudio.apicenter.gateway.web.MaccsTradeDefineVo;
import com.irdstudio.apicenter.gateway.web.view.JsonView;
import com.irdstudio.apicenter.gateway.web.view.View;

@Controller
@SuppressWarnings("unchecked")
public class UploadController implements IController {

	/* 文本日志输出 */
	private static final Logger logger = LoggerFactory.getLogger(UploadController.class);

	private static final long serialVersionUID = 1L;

	@Override
	public View execute(MaccsTradeDefineVo tradeDefine, MaccsPacket inPacket, HttpServletRequest request,
			HttpServletResponse response) throws MaccsException {
		MaccsPacket backPacket = null;
		// String appl=(String)inPacket.getValue("applSeq");
		String client = (String) inPacket.getValue("client");
		String appl = request.getParameter("applseq");
		String id_num = request.getParameter("id_num");
		String doc_type = request.getParameter("doc_type");
		String busi_flag = request.getParameter("flag");
		System.out.println("appl--" + appl);
		try {
			backPacket = this.uploadFile(request, response, appl, id_num, doc_type, busi_flag);
			response.setStatus(HttpServletResponse.SC_OK);
		} catch (ServletException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return new JsonView(request, response, backPacket);
	}

	protected void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// this.uploadFile(request,response); //上传文件
	}

	/**
	 * 上传文件处理
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	public MaccsPacket uploadFile(HttpServletRequest request, HttpServletResponse response, String appl, String id_num,
			String doc_type, String busi_flag) throws ServletException, IOException {
		MaccsPacket backPacket = null;
		response.setContentType("text/html;charset=utf-8");
		request.setCharacterEncoding("utf-8");
		HttpSession session = request.getSession();
		session.setAttribute("progressBar", 0); // 定义指定上传进度的Session变量
		String error = "";
		int maxSize = 50 * 1024 * 1024; // 单个上传文件大小的上限
		DiskFileItemFactory factory = new DiskFileItemFactory(); // 基于磁盘文件项目创建一个工厂对象
		ServletFileUpload upload = new ServletFileUpload(factory); // 创建一个新的文件上传对象
		File file = null;
		FileOutputStream fos =null;
		try {
			// 统计文件域个数及实际上传的文件个数
			int fileIndex = 0, fileUploadCount = 0;
			List items = upload.parseRequest(request);// 解析上传请求
			Iterator itr = items.iterator();// 枚举方法
			ArrayList<File> files = new ArrayList<File>();

			// File[] files=new File[items.size()-2];
			while (itr.hasNext()) {
				// 获取FileItem对象
				FileItem item = (FileItem) itr.next();
				// 判断是否为文件域
				if (!item.isFormField()) {
					fileIndex++;
					// 判断是否选择了文件,选择了则进行上传处理,否则不处理,跳过
					if (item.getName() != null && !item.getName().equals("")) {
						long upFileSize = item.getSize(); // 上传文件的大小
						String fileName = item.getName(); // 获取文件名
						String[] fileNameArr = fileName.split("\\.");
						Date date = new Date();
						fileName = "" + appl + (date.getYear() + 1900) + (date.getMonth() + 1) + date.getDate()
								+ date.getHours() + date.getMinutes() + date.getSeconds() + fileIndex + "."
								+ fileNameArr[fileNameArr.length - 1];// 重新获取文件名，避免中文
						logger.info("文件域[" + fileIndex + "],上传文件:" + item.getName() + ",文件大小:" + item.getSize());
						if (upFileSize > maxSize) {
							error = "您上传的文件太大，请选择不超过50M的文件";
							break;
						}
						// 获取根目录对应的真实物理路径并构造文件对象
						String uploadPath = PathUtil.getProjectRootPath() + "/upload";

						File uploadPathfile = new File(uploadPath);
						if (!uploadPathfile.exists() && !uploadPathfile.isDirectory()) {
							uploadPathfile.mkdir();
						}

						file = new File(uploadPath, fileName);
						files.add(file);
						InputStream is = item.getInputStream();
						int buffer = 1024; // 定义缓冲区的大小
						int length = 0;
						byte[] b = new byte[buffer];
						double percent = 0;
						fos = new FileOutputStream(file);
						while ((length = is.read(b)) != -1) {
							percent += length / (double) upFileSize * 100D; // 计算上传文件的百分比
							fos.write(b, 0, length); // 向文件输出流写读取的数据
							session.setAttribute("progressBar", Math.round(percent)); // 将上传百分比保存到Session中
						}
						fos.close();
						Thread.sleep(1000); // 线程休眠1秒
						fileUploadCount++; // 文件上传数+1
					} else {
						// 说明该 文件域没有选择要上传的文件,跳过
						logger.info("文件域[" + fileIndex + "],没有选择要上传的文件!");
						continue;
					}
				}
			}
			boolean boo = upload2ImageSys(files, appl, id_num, doc_type, busi_flag);
			if (boo == false) {
				error = "上传文件出错！";
			}

			// 如果文件域为0或实际上传的文件数为0,均说明没有上传文件,返回错误
			if (fileIndex == 0 || fileUploadCount == 0) {
				error = "没有选择上传文件！";
			}
		} catch (Exception e) {
			e.printStackTrace();
			error = "上传文件出现错误";
		} finally {
			try {
				if (fos != null) {
					fos.close();
					fos=null;
				}
			} catch (Exception e2) {
			}
			if (!"".equals(error)) {
				backPacket = MaccsPacketUtil.makeFailurePacket(error);
			} else {
				backPacket = MaccsPacketUtil.makeSimpleSuccessPacket("文件上传成功！");

			}
		}
		return backPacket;
	}

	/**
	 * 将文件上传到影像系统
	 * 
	 * @param files
	 *            上传的文件列表
	 * @param appl
	 * @param id_num
	 * @param doc_type
	 * @param busi_flag
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private boolean upload2ImageSys(ArrayList<File> files, String appl, String id_num, String doc_type,
			String busi_flag) throws ClientProtocolException, IOException {

		String bussid = "000CSCP001";
		CloseableHttpClient httpclient =null;
		// 创建HttpClient
		try {
			httpclient = HttpClients.createDefault();

			MaccsBaseDAO jdbcDao = BeanUtils.getBean(MaccsBaseDAO.class);
			String Url = jdbcDao
					.queryForObject(
							"select FORWARD_CHANNEL_URL from app_channel_forward where FORWARD_CHANNEL_ID=? and APP_ID=? ",
							new Object[] { "JSH_YCMS", "2002" }, String.class);

			logger.info("准备上传到影像系统地址:" + Url);
			HttpPost httpPost = new HttpPost(Url);
			String sysidknl = "";
			String bussidknl = "";
			String tarUrl = "";
			String tarIP = "";
			String tarPort = "";
			String tarUser = "";
			String tarPwd = "";
			String retCode = "";
			String retDesp = "";
			String modelDir = "";// 虚拟目录
			Map metadata = null;
			Map server = null;
			Map mac = null;
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			Map<String, Object> backPacket = null;

			logger.info("1.向影像系统发送M000,以获得初始化参数...");
			String key = "type";
			String value = "M000";

			nvps.add(new BasicNameValuePair(key, value));
			key = "message";
			value = "<?xml version=\"1.0\" encoding=\"gbk\" ?><ROOT><TRANSDATA><CMD_CODE>M000</CMD_CODE></TRANSDATA><METADATA><VER>2000</VER><SYSID>xd0001</SYSID><BUSSID>"
					+ bussid
					+ "</BUSSID><TELLER_NO>1000000001</TELLER_NO><TRANSMOD>FTP</TRANSMOD><EXT/></METADATA></ROOT>";
			nvps.add(new BasicNameValuePair(key, value));
			logger.info("发送的M000报文：" + value);
			httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));

			// 处理返回结果
			CloseableHttpResponse response = httpclient.execute(httpPost);
			try {
				logger.info("响应状态：" + response.getStatusLine());
				if (response.getStatusLine().getStatusCode() == 200) {

					// 读取http返回的内容
					HttpEntity entity = response.getEntity();
					String result = EntityUtils.toString(entity, "UTF-8");
					EntityUtils.consume(entity);
					logger.info("响应内容：" + result);

					XmlMapper xmlMapper = new XmlMapper();

					// 允许出现特殊字符和转义符
					xmlMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS,
							true);

					// 允许出现单引号
					xmlMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
					backPacket = xmlMapper.readValue(result, Map.class);

				} else {
					logger.error("未接收到响应信息，调用失败!");
					return false;
				}
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}

			finally {
				response.close();
			}

			metadata = (Map) backPacket.get("METADATA");
			server = (Map) metadata.get("SERVER");
			mac = (Map) server.get("MAC");
			sysidknl = (String) metadata.get("SYSIDKNL");
			bussidknl = (String) metadata.get("BUSSIDKNL");
			tarUrl = (String) mac.get("URL");
			tarIP = (String) mac.get("IP");
			tarPort = (String) mac.get("PORT");
			tarUser = (String) mac.get("USER");
			tarPwd = (String) mac.get("PWD");
			retCode = (String) mac.get("RETCODE");
			retDesp = (String) mac.get("RETDESP");
			String teller_no = (String) metadata.get("TELLER_NO");
			logger.debug("FTP地址：" + tarIP);
			logger.debug("FTP端口：" + tarPort);

			logger.info("2.发送M011,通知影像系统要上传的信息及创建相关的空白文档...");
			String keyM011 = "type";
			String valueM011 = "M011";
			List<NameValuePair> nvpsM011 = new ArrayList<NameValuePair>();
			nvpsM011.add(new BasicNameValuePair(keyM011, valueM011));
			keyM011 = "message";
			valueM011 = "<?xml version=\"1.0\" encoding=\"gbk\"?><ROOT><TRANSDATA><CMD_CODE>M011</CMD_CODE></TRANSDATA><METADATA><VER>2000</VER><SYSIDKNL>"
					+ sysidknl
					+ "</SYSIDKNL><BUSSIDKNL>"
					+ bussidknl
					+ "</BUSSIDKNL><TELLER_NO>"
					+ teller_no
					+ "</TELLER_NO><APPL>"
					+ appl
					+ "</APPL><PRDNO>0000000000</PRDNO><MOD>0</MOD><EXT/></METADATA></ROOT>";
			nvpsM011.add(new BasicNameValuePair(keyM011, valueM011));
			logger.info("发送M011报文:" + valueM011);
			httpPost.setEntity(new UrlEncodedFormEntity(nvpsM011, "UTF-8"));
			CloseableHttpResponse responseM011 = httpclient.execute(httpPost);
			// 处理返回结果
			Map<String, Object> backPacketM011 = null;
			try {
				logger.info("响应状态：" + responseM011.getStatusLine());
				if (responseM011.getStatusLine().getStatusCode() == 200) {

					// 读取http返回的内容
					HttpEntity entity = responseM011.getEntity();
					String result = EntityUtils.toString(entity, "UTF-8");
					EntityUtils.consume(entity);
					logger.info("响应内容：" + result);

					XmlMapper xmlMapper = new XmlMapper();

					// 允许出现特殊字符和转义符
					xmlMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS,
							true);

					// 允许出现单引号
					xmlMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
					backPacketM011 = xmlMapper.readValue(result, Map.class);
				} else {
					logger.error("未接收到响应信息，调用失败!");
				}
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			} finally {
				responseM011.close();
			}
			Map tmpaddrMap = null;
			metadata = (Map) backPacketM011.get("METADATA");
			tmpaddrMap = (Map) backPacketM011.get("RET");
			String tmpaddr = (String) tmpaddrMap.get("TMPADDR");
			String doc_id = (String) metadata.get("DOC_ID");
			String batch = (String) tmpaddrMap.get("BATCH");
			String writepath = (String) tmpaddrMap.get("WRITEPATH");
			System.out.println("writepath" + writepath);

			int port = tarPort == null ? 0 : Integer.parseInt(tarPort);
			UploadFTPClient uploadFTPClient = new UploadFTPClient();

			logger.info("3.根据M000返回的FTP地址,将要上传的文档上传到该ftp上...");
			boolean fl = uploadFTPClient.upLoadFromProduction(tarIP, port,
					tarUser, tarPwd, writepath, files);
			// 没上传成本，不通知
			if (!fl) {
				return false;
			}

			logger.info("4.发送M003,通知影像系统将FTP上的文档归到影像系统下...");
			String keyM003 = "type";
			String valueM003 = "M003";
			List<NameValuePair> nvpsM003 = new ArrayList<NameValuePair>();
			nvpsM003.add(new BasicNameValuePair(keyM003, valueM003));
			keyM003 = "message";
			int seq = 1;
			valueM003 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ROOT><TRANSDATA><CMD_CODE>M003</CMD_CODE></TRANSDATA><METADATA><VER>2000</VER><SYSIDKNL>"
					+ sysidknl
					+ "</SYSIDKNL><BUSSIDKNL>"
					+ bussidknl
					+ "</BUSSIDKNL><TELLER_NO>"
					+ teller_no
					+ "</TELLER_NO><DOC_ID>"
					+ doc_id
					+ "</DOC_ID><THUMB>0</THUMB><BATCH>"
					+ batch
					+ "</BATCH><WRITEPATH>"
					+ writepath
					+ "</WRITEPATH><ARCHIVEFILES  TOTAL=\""
					+ files.size()
					+ "\">";
			String[] fileNameArr;
			for (File file : files) {
				fileNameArr = file.getName().split("\\.");
				// 把视频文件放到其他虚拟目录中
				System.out.println("加入文件:" + file.getName());
				if ("mp4".equalsIgnoreCase(fileNameArr[fileNameArr.length - 1])
						|| "3gp"
								.equalsIgnoreCase(fileNameArr[fileNameArr.length - 1])
						|| "mov"
								.equalsIgnoreCase(fileNameArr[fileNameArr.length - 1])) {
					modelDir = "其他";
				} else {
					modelDir = "身份信息";
				}
				System.out.println(file.getName() + "获取file的大小："
						+ file.length());
				valueM003 += "<ARCHIVEFILE SEQ=\"" + seq
						+ "\" MOD=\"0\" FILE=\"\" DIR=\"" + modelDir
						+ "\"><PARAM><KEY>FILE</KEY><VALUE>" + file.getName()
						+ "</VALUE></PARAM>"
						+ "<PARAM><KEY>FILE_SIZE</KEY><VALUE>" + file.length()
						+ "</VALUE></PARAM></ARCHIVEFILE>";
				seq++;
			}
			valueM003 += "</ARCHIVEFILES><EXT/></METADATA></ROOT>";
			logger.info("发送M003报文:" + valueM003);
			nvpsM003.add(new BasicNameValuePair(keyM003, valueM003));
			logger.debug("发送报文:" + valueM003);
			httpPost.setEntity(new UrlEncodedFormEntity(nvpsM003, "UTF-8"));

			// 处理返回结果
			response = httpclient.execute(httpPost);
			try {
				logger.info("响应状态：" + response.getStatusLine());
				if (response.getStatusLine().getStatusCode() == 200) {

					// 读取http返回的内容
					HttpEntity entity = response.getEntity();
					String result = EntityUtils.toString(entity, "UTF-8");
					EntityUtils.consume(entity);
					logger.info("响应内容：" + result);

					XmlMapper xmlMapper = new XmlMapper();

					// 允许出现特殊字符和转义符
					xmlMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS,
							true);

					// 允许出现单引号
					xmlMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
					backPacket = xmlMapper.readValue(result, Map.class);

				} else {
					logger.error("未接收到响应信息，调用失败!");
				}
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			} finally {
				response.close();
			}
			logger.info("5.向影像系统上传文件完成!!!");

			return true;
		} catch (Exception e) {
			logger.info("调用upload2ImageSys()方法异常");
			throw new RuntimeException(e.getMessage(),e);
		}finally{
			try {
				if (httpclient != null) {
					httpclient.close();
					httpclient = null;
				}
			} catch (Exception e2) {
			}
		}
	}

	public static void main(String[] args) {
		// String docName,String docNum,String orderNum,String page,String
		// positionX,String positionY,String userCode,String title
		UploadController u = new UploadController();
	}

}
